
    /**  
    * @Title: ImportLockerBeanDefinitionRegistrar.java
    * @Package com.efast.cafe.framework.redis.locker
    * @Description: TODO(用一句话描述该文件做什么)
    * @author Administrator
    * @date 2019年1月17日
    * @version V1.0  
    */
    
package com.efast.cafe.framework.redis.locker.config;

import java.util.ArrayList;
import java.util.List;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import com.efast.cafe.framework.redis.locker.RedissonDistributedLocker;
import com.efast.cafe.util.StringUtil;

/**
    * @ClassName: ImportLockerBeanDefinitionRegistrar
    * @Description: 注册分布式锁的bean list
    * @author xuanming.feng
    * @date 2019年1月17日
    *
    */
@Configuration
@ConditionalOnClass(Config.class)
@ConditionalOnProperty(name="locker.enable",havingValue="true")
public class ImportLockerBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar,EnvironmentAware{

	Logger logger = LoggerFactory.getLogger(ImportLockerBeanDefinitionRegistrar.class);
	//分布式锁bean的前缀
	protected String LOCKER_BEAN_PRE="locker_";
	
	private RedissonListProperties redissonListProperties;
	  
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
		List<RedissonProperties> list = redissonListProperties.getRedisson();
		list.forEach(p->{
			//不存在bean 则注册
			if(!registry.containsBeanDefinition(LOCKER_BEAN_PRE+p.getLockGroup())){
				Config config = new Config();
				if(StringUtil.isNotBlank(p.getMasterName())){//集群模式
					 SentinelServersConfig serverConfig = config.useSentinelServers().
				        		addSentinelAddress(p.getSentinelAddresses())
				                .setMasterName(p.getMasterName())
				                .setTimeout(p.getTimeout()).setDatabase(p.getDatabase())
				                .setMasterConnectionPoolSize(p.getMasterConnectionPoolSize())
				                .setSlaveConnectionPoolSize(p.getSlaveConnectionPoolSize());
					 if(StringUtil.isNotBlank(p.getPassword())) {
				            serverConfig.setPassword(p.getPassword());
				      }
				}else{//单机模式
					 SingleServerConfig serverConfig = config.useSingleServer()
				                .setAddress(p.getAddress())
				                .setTimeout(p.getTimeout()).setDatabase(p.getDatabase())
				                .setConnectionPoolSize(p.getConnectionPoolSize())
				                .setConnectionMinimumIdleSize(p.getConnectionMinimumIdleSize());
				        if(StringUtil.isNotBlank(p.getPassword())) {
				            serverConfig.setPassword(p.getPassword());
				        }
				}
				RedissonClient redissonClient = Redisson.create(config);
				RootBeanDefinition definition = new RootBeanDefinition();  
				definition.setBeanClass(RedissonDistributedLocker.class);
				ConstructorArgumentValues argumentValues = new ConstructorArgumentValues(); 
				argumentValues.addGenericArgumentValue(redissonClient); 
				definition.setConstructorArgumentValues(argumentValues);
				registry.registerBeanDefinition(LOCKER_BEAN_PRE+p.getLockGroup(), definition);
				logger.info("registered locker bean :"+LOCKER_BEAN_PRE+p.getLockGroup());
				
				
			}else{
				logger.warn("this locker beanName has been registered. bean name : "+LOCKER_BEAN_PRE+p.getLockGroup());
			}
		});
		
	}

	
	    /* (非 Javadoc)
	    * 
	    * 
	    * @param environment
	    * @see org.springframework.context.EnvironmentAware#setEnvironment(org.springframework.core.env.Environment)
	    */
	@Override
	public void setEnvironment(Environment environment) {
		redissonListProperties = new RedissonListProperties();
		List<RedissonProperties> redissonList = new ArrayList<>();
		RelaxedPropertyResolver rp = new RelaxedPropertyResolver(environment,"locker.");
		Boolean lockerEnable = Boolean.parseBoolean(rp.getProperty("enable"));
		redissonListProperties.setEnable(lockerEnable);
		String groups = rp.getProperty("groups");
		String[] groupArray = groups.split(",");
		for(String group : groupArray){
			RedissonProperties subredisson = new RedissonProperties();
			RelaxedPropertyResolver subrp = new RelaxedPropertyResolver(environment,"locker."+group+".");
			String timeout = subrp.getProperty("timeout");
			String database = subrp.getProperty("database");
			String password = subrp.getProperty("password");
			String address = subrp.getProperty("address");
			String connectionPoolSize = subrp.getProperty("connection-pool-size");
			String connectionMinimumIdleSize = subrp.getProperty("connection-minimum-idle-size");
			String slaveConnectionPoolSize = subrp.getProperty("slave-connection-pool-size");
			String masterConnectionPoolSize = subrp.getProperty("master-connection-pool-size");
			String sentinelAddresses = subrp.getProperty("sentinel-addresses");
			String masterName = subrp.getProperty("master-name");
			
			subredisson.setLockGroup(group);
			if(StringUtil.isNotBlank(timeout)){
				subredisson.setTimeout(Integer.parseInt(timeout));
			}
			if(StringUtil.isNotBlank(database)){
				subredisson.setDatabase(Integer.parseInt(database));
			}
			if(StringUtil.isNotBlank(password)){
				subredisson.setPassword(password);
			}
			if(StringUtil.isNotBlank(address)){
				subredisson.setAddress(address);
			}
			if(StringUtil.isNotBlank(connectionPoolSize)){
				subredisson.setConnectionPoolSize(Integer.parseInt(connectionPoolSize));
			}
			if(StringUtil.isNotBlank(connectionMinimumIdleSize)){
				subredisson.setConnectionMinimumIdleSize(Integer.parseInt(connectionMinimumIdleSize));
			}
			if(StringUtil.isNotBlank(slaveConnectionPoolSize)){
				subredisson.setSlaveConnectionPoolSize(Integer.parseInt(slaveConnectionPoolSize));
			}
			if(StringUtil.isNotBlank(masterConnectionPoolSize)){
				subredisson.setMasterConnectionPoolSize(Integer.parseInt(masterConnectionPoolSize));
			}
			if(StringUtil.isNotBlank(sentinelAddresses)){
				subredisson.setSentinelAddresses(sentinelAddresses);
			}
			if(StringUtil.isNotBlank(masterName)){
				subredisson.setMasterName(masterName);
			}
			redissonList.add(subredisson);
		}
		redissonListProperties.setRedisson(redissonList);
	}

}
